package com.winchain.chainbill.bill.biz.send.service.impl;

import com.shell.bee.acct.account.po.AcctBas;
import com.shell.bee.acct.account.util.VirtualAcctUtil;
import com.shell.bee.acct.transaction.vo.AcctInfo;
import com.shell.bee.base.exception.UnCheckMsgException;
import com.shell.bee.base.utils.DateUtil;
import com.shell.bee.base.utils.StringUtil;
import com.shell.bee.contract.ContService;
import com.shell.bee.contract.po.ContBas;
import com.shell.constant.rel.AssetCode;
import com.shell.feign.PubDateFeign;
import com.shell.framework.utils.CommonDataUtil;
import com.shell.framework.utils.MathsUtil;
import com.shell.framework.utils.ParameterHelper;
import com.shell.framework.utils.SysDateUtil;
import com.shell.governor.modules.vo.ParameterVo;
import com.winchain.chainbill.ChainBillUtil;
import com.winchain.chainbill.basic.cus.po.CusRec;
import com.winchain.chainbill.basic.cus.service.CusRecService;
import com.winchain.chainbill.bill.base.po.CbDct;
import com.winchain.chainbill.bill.base.po.CbDctQt;
import com.winchain.chainbill.bill.base.po.CbRec;
import com.winchain.chainbill.bill.base.po.CbRpur;
import com.winchain.chainbill.bill.base.po.CbSnd;
import com.winchain.chainbill.bill.base.po.CbXfe;
import com.winchain.chainbill.bill.base.service.CbDctQtService;
import com.winchain.chainbill.bill.base.service.CbRecService;
import com.winchain.chainbill.bill.biz.send.service.BillCheckService;
import com.winchain.chainbill.constant.BillConstants;
import com.winchain.chainbill.risk.utill.RateUtil;
import com.winchain.chainbill.trade.service.BillAcctService;
import java.math.BigDecimal;
import java.text.ParseException;
import java.util.Date;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

@Service("billCheckService")
public class BillCheckServiceImpl implements BillCheckService {
	@Autowired
	private CusRecService basCusService;
	@Autowired
	private BillAcctService billAcctService;
	@Autowired
	private CbRecService cbRecService;
	@Autowired
	private PubDateFeign dateFeign;
	@Autowired
	private ContService contService;
	@Autowired
	private CbDctQtService cbDctQtService;

	public String checkBillSnd(CbRec bill, CbSnd send) {
		String msg = checkSndData(bill, send);
		if (StringUtil.notEmpty(msg)) {
			return msg;
		}
		String buyerId = send.getBuyerId();
		String billType = bill.getBillType();
		BigDecimal billAmt = bill.getBillAmt();
		BigDecimal bailRatio = send.getBailRatio();
		String finId = "";

		finId = bill.getFinId();

		String grpId = bill.getGrpId();
		msg = checkBalance(buyerId, grpId, finId, billType, billAmt, bailRatio);
		if (StringUtil.notEmpty(msg)) {
			return msg;
		}
		msg = checkBuyer(send);
		if (StringUtil.notEmpty(msg)) {
			return msg;
		}
		msg = checkSeller(send);
		if (StringUtil.notEmpty(msg)) {
			return msg;
		}
		msg = checkBillAmt(billAmt, grpId);
		if (StringUtil.notEmpty(msg)) {
			return msg;
		}
		String ExpDate = bill.getExpDate();
		msg = checkExpDate(billType, ExpDate, grpId);
		if (StringUtil.notEmpty(msg)) {
			return msg;
		}
		return "";
	}

	public String checkBillXfe(CbRec record, CbXfe... xfes) {
		String msg = checkXfeData(record, xfes);
		if (StringUtil.notEmpty(msg)) {
			return msg;
		}
		msg = checkXfeDate(record, xfes);
		if (StringUtil.notEmpty(msg)) {
			return msg;
		}
		msg = checkBuyer(xfes);
		if (StringUtil.notEmpty(msg)) {
			return msg;
		}
		msg = checkSeller(xfes);
		if (StringUtil.notEmpty(msg)) {
			return msg;
		}
		msg = checkXfeMoney(record, xfes);
		if (StringUtil.notEmpty(msg)) {
			return msg;
		}
		CbXfe xfe;
		String buyerId;
		if (xfes.length == 1) {
			xfe = xfes[0];
			buyerId = CommonDataUtil.getCurEntId();
			if (buyerId.equals(xfe.getSellerId())) {
				return "����������������";
			}
		}
		if (StringUtil.emptyAndNull(String.valueOf(record.getBillAmt()))) {
			return "����������";
		}
		for (int str1 = 0; str1 < xfes.length; str1++) {
			xfe = xfes[str1];
			BigDecimal billAmt = xfe.getBillAmt();
			if ((StringUtil.emptyAndNull(String.valueOf(billAmt)))
					|| (billAmt.setScale(2, 4).compareTo(BigDecimal.ZERO) <= 0)) {
				return "��������������������������0";
			}
		}
		msg = checkXfeDfr(record, xfes);
		if (StringUtil.notEmpty(msg)) {
			return msg;
		}
		return "";
	}

	private String checkXfeDfr(CbRec record, CbXfe... xfes) {
		String dfrExpDate = null;
		for (CbXfe xfe : xfes) {
			dfrExpDate = xfe.getExpDate();
			int days = DateUtil.getDaysBetween(record.getExpDate(), dfrExpDate);
			if (days > 0) {
				String acctNo = getAcctNo(record.getFinId());
				if (StringUtil.emptyAndNull(acctNo)) {
					return "��������������������������������������������";
				}
			}
		}
		return "";
	}

	private String checkSndData(CbRec bill, CbSnd send) {
		ParameterVo sndNeedInterest = ParameterHelper.getCommonParameter("SND_NEED_INTEREST");
		if (sndNeedInterest.getParmValue().equals("1")) {
			String sndFixedRate = RateUtil.getFixedRate(bill.getGrpId(), bill.getFinId(), "snd_fixed_rate");
			String sndVariableRate = RateUtil.getVariableRate(bill.getGrpId(), bill.getFinId(),
					CommonDataUtil.getCurEntId(), "snd_variable_rate");
			if ((StringUtil.empty(sndFixedRate)) || (StringUtil.empty(sndVariableRate))) {
				return "��������������������������������������";
			}
		}
		if (StringUtil.emptyAndNull(bill.getBillType())) {
			return "��������������";
		}
		if (StringUtil.emptyAndNull(bill.getBillCode())) {
			return "��������������";
		}
		if (StringUtil.emptyAndNull(bill.getBillAmt().toString())) {
			return "��������������";
		}
		if (StringUtil.emptyAndNull(bill.getSndDate())) {
			return "������������";
		}
		boolean isHoliday = this.dateFeign.isHoliday(bill.getExpDate());
		if (isHoliday) {
			return "��������������������";
		}
		if (StringUtil.emptyAndNull(bill.getExpDate())) {
			return "����������������";
		}
		if (StringUtil.emptyAndNull(bill.getGrpId())) {
			return "������id����";
		}
		if (StringUtil.emptyAndNull(send.getBuyerId())) {
			return "��������id������";
		}
		if (StringUtil.emptyAndNull(send.getSellerId())) {
			return "��������id������";
		}
		String sendDate = bill.getSndDate();
		if ("1".equals(bill.getBillType())) {
			String systemDate = DateUtil.getSystemDate();
			if (DateUtil.compare(sendDate, systemDate) == -1) {
				return "������������������������";
			}
		}
		if (bill.getExpDate().compareTo(sendDate) < 0) {
			return "��������������������������������";
		}
		if (send.getBuyerId().equals(send.getSellerId())) {
			return "������������������������";
		}
		BigDecimal bailRatio = send.getBailRatio();
		if ((bailRatio != null) && (bailRatio.compareTo(new BigDecimal(0)) > 0)) {
			if (StringUtil.emptyAndNull(send.getBailAcct())) {
				return "��������������������������������������������������������";
			}
			if (StringUtil.emptyAndNull(send.getCurAcct())) {
				return "����������������������������������������������������";
			}
		}
		return "";
	}

	private String checkBalance(String buyerId, String grpId, String finId, String billType, BigDecimal billAmt,
			BigDecimal bailRatio) {
		String retValue = "";

		BigDecimal blocked = null;
		ContBas contBas = this.contService.getContBas(finId, buyerId, "40", "6");
		AcctInfo acctInfo = new AcctInfo();
		acctInfo.setCustId(buyerId);
		acctInfo.setBkpPrdCode(grpId);
		acctInfo.setBkpCttNo(contBas.getContSn());
		acctInfo.setAcctType("1");
		acctInfo.setCurrCode(AssetCode.XQT.name());
		acctInfo = this.billAcctService.getAcctInfo(acctInfo);

		BigDecimal blc = acctInfo.getAcctBlc();
		blocked = acctInfo.getAcctBlk();
		blc = blc.subtract(blocked);
		BigDecimal amt = billAmt.multiply(new BigDecimal(100).subtract(bailRatio).divide(new BigDecimal(100)));
		if (amt.compareTo(blc) > 0) {
			retValue = "����������������������!";
		}
		String acctNo = getAcctNo(finId);
		if (StringUtil.emptyAndNull(acctNo)) {
			return "��������������������������������������������";
		}
		return retValue;
	}

	private String checkBuyer(CbSnd send) {
		String buyerId = send.getBuyerId();
		CusRec cus = (CusRec) this.basCusService.selectByKey(buyerId);
		String cusState = cus.getCusState();
		if (!"E".equals(cusState)) {
			return "����������������������������������������������";
		}
		String acctNo = getAcctNo(buyerId);
		if (StringUtil.emptyAndNull(acctNo)) {
			return "����������������������";
		}
		send.setBuyerAcct(acctNo);
		return "";
	}

	private String checkBuyer(CbXfe... xfes) {
		String buyerId = CommonDataUtil.getCurEntId();
		CusRec cus = (CusRec) this.basCusService.selectByKey(buyerId);
		String cusState = cus.getCusState();
		if (!"E".equals(cusState)) {
			return "��������������������������������������������";
		}
		String acctNo = getAcctNo(buyerId);
		if (StringUtil.emptyAndNull(acctNo)) {
			return "����������������������";
		}
		for (CbXfe xfe : xfes) {
			xfe.setBuyerAcct(acctNo);
		}
		return "";
	}

	private String checkSeller(CbXfe... xfes) {
		for (CbXfe xfe : xfes) {
			String sellerId = xfe.getSellerId();
			CusRec cus = (CusRec) this.basCusService.selectByKey(sellerId);
			if (cus == null) {
				return "������������������������";
			}
			String cusState = cus.getCusState();
			if (!"E".equals(cusState)) {
				return "��������[" + cus.getCusName() + "]��������������������������������������������������";
			}
			String acctNo = getAcctNo(sellerId);
			if (StringUtil.emptyAndNull(acctNo)) {
				return "��������[" + cus.getCusName() + "]����������������������������������������������������������";
			}
			xfe.setSellerAcct(acctNo);
		}
		return "";
	}

	private String getAcctNo(String cusId) {
		String acctNo = "";
		AcctBas acct = this.billAcctService.getAcctBas(cusId, null, "00");
		if (acct != null) {
			acctNo = acct.getAcctNo();
		}
		return acctNo;
	}

	private String checkSeller(CbSnd send) {
		String sellerId = send.getSellerId();
		CusRec cus = (CusRec) this.basCusService.selectByKey(sellerId);
		if (cus == null) {
			return "������������������������";
		}
		String cusState = cus.getCusState();
		if (!"E".equals(cusState)) {
			return "��������[" + cus.getCusName() + "]��������������������������������������������������";
		}
		String acctNo = getAcctNo(sellerId);
		if (StringUtil.emptyAndNull(acctNo)) {
			return "��������[" + cus.getCusName() + "]����������������������������������������������������������";
		}
		send.setSellerAcct(acctNo);
		return "";
	}

	private String checkBillAmt(BigDecimal billAmt, String grpId) {
		String retValue = "";

		ParameterVo parm = ParameterHelper.getParameter("6", "BILL_LIM_MONEY", grpId);
		if (parm == null) {
			throw new UnCheckMsgException("����������������:\"����������������\"");
		}
		String limAmt = parm.getParmValue();
		if ((!StringUtil.emptyAndNull(limAmt)) && (billAmt.compareTo(new BigDecimal(limAmt)) > 0)) {
			retValue = "��������������������" + limAmt + "����";
		}
		return retValue;
	}

	private String checkExpDate(String billType, String ExpDate, String grpId) {
		StringBuilder builder = new StringBuilder();
		if (DateUtil.getSystemDate().equals(ExpDate)) {
			ParameterVo parm = null;
			String limTim = "";
			String type = "";
			if ("1".equals(billType)) {
				type = "��������";

				parm = ParameterHelper.getParameter("6", "CB_MEM_OUTPUT_LIM_TIM", grpId);
			} else {
				type = "������";
				parm = ParameterHelper.getCommonParameter("CB_SUP_OUTPUT_LIM_TIM");
			}
			if (parm == null) {
				throw new RuntimeException("����������������" + type + "������������");
			}
			limTim = parm.getParmValue();

			Date systemTime = DateUtil.transferDate(DateUtil.getSystemTime(), "HHmmss", "HH:mm");
			Date limitTime = DateUtil.transferDate(limTim, "HH:mm", "HH:mm");
			if (limitTime.compareTo(systemTime) < 1) {
				builder.append("��������������������������������������������").append(limTim)
						.append("������������������������");
			}
		}
		return builder.toString();
	}

	private String checkXfeMoney(CbRec record, CbXfe... xfes) {
		BigDecimal transMoney = new BigDecimal(0);
		int size = xfes.length;
		if (size == 1) {
			transMoney = record.getBillAmt();
		} else if (size > 1) {
			for (CbXfe xfe : xfes) {
				transMoney = transMoney.add(xfe.getBillAmt());
			}
		}
		CbRec cbRecord = (CbRec) this.cbRecService.selectByKey(record.getBillId());
		if (transMoney.compareTo(cbRecord.getBillAmt()) == 1) {
			return "������������������������" + cbRecord.getBillAmt();
		}
		return "";
	}

	private String checkXfeDate(CbRec record, CbXfe... xfes) {
		String transferDate = "";
		String dfrExpDate = "";
		String ExpDate = "";
		for (CbXfe xfe : xfes) {
			transferDate = xfe.getXfeDate();
			dfrExpDate = xfe.getExpDate();
			ExpDate = record.getExpDate();
			if (DateUtil.compare(transferDate, ExpDate) == 0) {
				return "��������������������������";
			}
			if ((!StringUtil.emptyAndNull(dfrExpDate)) && (DateUtil.compare(transferDate, dfrExpDate) >= 0)) {
				return "����������������������������";
			}
			if (DateUtil.compare(transferDate, ExpDate) >= 0) {
				return "����������������������������";
			}
		}
		return "";
	}

	private String checkXfeData(CbRec record, CbXfe... xfes) {
		StringBuilder builder = new StringBuilder();
		int counter = 1;
		String deferred = "";
		BigDecimal xfeMoney = null;
		String dfrExpDate = "";
		Date from = null;
		String preExprDate = "";
		Date to = null;
		BigDecimal dfrRate = null;
		BigDecimal dfrInt = null;
		for (CbXfe xfe : xfes) {
			if (StringUtil.emptyAndNull(xfe.getSellerId())) {
				builder.append("��" + counter + "����������������ID������");
			}
			deferred = xfe.getDeferred();
			if ("1".equals(deferred)) {
				xfeMoney = xfe.getBillAmt();
				dfrExpDate = xfe.getExpDate();
				preExprDate = record.getExpDate();
				try {
					from = DateUtil.getDate(dfrExpDate, "yyyyMMdd");
					to = DateUtil.getDate(preExprDate, "yyyyMMdd");
				} catch (ParseException e) {
					throw new RuntimeException("������������", e);
				}
				int days = DateUtil.getDaysBetween(from, to);

				dfrRate = xfe.getDfrRate();
				dfrInt = xfe.getDfrInt();

				BigDecimal calMoney = MathsUtil.mathInterest(xfeMoney, dfrRate, days);
				if (calMoney.compareTo(dfrInt) != 0) {
					builder.append("��" + counter + "��������������������[").append(dfrInt)
							.append("]������������������[").append(calMoney).append("]������");
				}
			}
			counter++;
		}
		return builder.toString();
	}

	private String checkSellData(CbRec record, CbDct sell) {
		StringBuilder builder = new StringBuilder();
		if (StringUtil.emptyAndNull(sell.getBillId())) {
			builder.append("��������������");
		}
		return builder.toString();
	}

	private String checkSellDate(CbRec record, CbDct sell) {
		String dctDate = sell.getDctDate();
		String expDate = record.getExpDate();
		if (DateUtil.compare(dctDate, expDate) == 0) {
			return "��������������������������";
		}
		if (DateUtil.compare(dctDate, expDate) >= 0) {
			return "����������������������������";
		}
		return "";
	}

	private String checkSeller(CbDct sell) {
		String sellerId = CommonDataUtil.getCurEntId();
		CusRec cus = (CusRec) this.basCusService.selectByKey(sellerId);
		String sellerAcct = sell.getSellerAcct();
		String cusState = cus.getCusState();
		if (!"E".equals(cusState)) {
			return "��������������������������������������������";
		}
		AcctBas acct = null;
		if ((ChainBillUtil.onlinePay()) && (VirtualAcctUtil.onVirtual())) {
			acct = this.billAcctService.getAcctBas(sellerId, null, "00");
			sell.setSellerAcct(acct.getAcctNo());
		} else {
			acct = this.billAcctService.getCard(sellerAcct);
		}
		if (acct == null) {
			return "��������������������";
		}
		String custId = acct.getCustId();
		if (!sellerId.equals(custId)) {
			return sellerAcct + "������������������������";
		}
		return "";
	}

	private String checkFin(CbRec prnt, CbDct sell) {
		String finId = sell.getFinId();
		CusRec cus = (CusRec) this.basCusService.selectByKey(finId);
		if (cus == null) {
			return "��������������������������";
		}
		String cusState = cus.getCusState();
		if (!"E".equals(cusState)) {
			return "��������[" + cus.getCusName() + "]��������������������������������������������������";
		}
		String acctNo = getAcctNo(finId);
		if (StringUtil.emptyAndNull(acctNo)) {
			return "��������������������������������������������";
		}
		sell.setFinId(finId);
		sell.setFinAcct(acctNo);

		return "";
	}

	private String checkSellMoney(CbRec record, CbDct sell) {
		BigDecimal sellMoney = new BigDecimal(0);
		sellMoney = sell.getDctAmt();
		CbRec cbRecord = (CbRec) this.cbRecService.selectByKey(record.getBillId());
		if (sellMoney.compareTo(cbRecord.getBillAmt()) == 1) {
			return "������������������������" + cbRecord.getBillAmt();
		}
		return "";
	}

	public String checkBillDct(CbRec record, CbDct dct) {
		String msg = checkSellData(record, dct);
		if (StringUtil.notEmpty(msg)) {
			return msg;
		}
		msg = checkSellDate(record, dct);
		if (StringUtil.notEmpty(msg)) {
			return msg;
		}
		msg = checkSeller(dct);
		if (StringUtil.notEmpty(msg)) {
			return msg;
		}
		msg = checkFin(record, dct);
		if (StringUtil.notEmpty(msg)) {
			return msg;
		}
		msg = checkSellMoney(record, dct);
		if (StringUtil.notEmpty(msg)) {
			return msg;
		}
		if (StringUtil.emptyAndNull(String.valueOf(record.getBillAmt()))) {
			return "����������";
		}
		BigDecimal sellMoney = dct.getDctAmt();
		if ((StringUtil.emptyAndNull(String.valueOf(sellMoney)))
				|| (sellMoney.setScale(2, 4).compareTo(BigDecimal.ZERO) <= 0)) {
			return "��������������������������0";
		}
		if (StringUtil.emptyAndNull(dct.getQtId())) {
			if (!"FIN_BUYER".equals(dct.getFinTagCode())) {
				return "��������id����";
			}
		} else {
			CbDctQt dctQt = (CbDctQt) this.cbDctQtService.selectByKey(dct.getQtId());
			if ("1".equals(dctQt.getQtState())) {
				return "��������������";
			}
			if (dctQt.getQtAmt() == null) {
				return "��������������";
			}
			BigDecimal qtAvailAmt = dctQt.getAvailAmt();
			if ((qtAvailAmt != BillConstants.QT_AMT_NO_LIMIT) && (sellMoney.compareTo(qtAvailAmt) > 0)) {
				return "����������������";
			}
		}
		if ((dct.isUploadInvoiceDefer()) && (dct.getCusDfrDays() == 0)) {
			return "����������������0";
		}
		ParameterVo blTimes = ParameterHelper.getParameter("6", "DCT_LIM_BL_TIM", record.getGrpId());
		if ((blTimes != null) && (!StringUtil.emptyAndNull(blTimes.getParmValue()))) {
			String[] strings = blTimes.getParmValue().split(",");
			if ((!SysDateUtil.compareTime(strings[0] + ":00")) || (SysDateUtil.compareTime(strings[1] + ":59"))) {
				return "��������������������" + strings[0] + "-" + strings[1] + ",������������������������";
			}
		}
		return "";
	}

	public String checkBillRpur(CbRec record, CbRpur rpur, CbDct dct) {
		String msg = checkRpurData(record, rpur);
		if (StringUtil.notEmpty(msg)) {
			return msg;
		}
		msg = checkBuyDate(record, rpur);
		if (StringUtil.notEmpty(msg)) {
			return msg;
		}
		msg = checkBuyer(rpur);
		if (StringUtil.notEmpty(msg)) {
			return msg;
		}
		if (StringUtil.emptyAndNull(String.valueOf(rpur.getRpurAmt()))) {
			return "����������";
		}
		String rpurFixedRate = RateUtil.getFixedRate(record.getGrpId(), dct.getFinId(), "rpur_fixed_rate");
		if (StringUtil.empty(rpurFixedRate)) {
			return "��������������������������������������";
		}
		return "";
	}

	private String checkRpurData(CbRec record, CbRpur rpur) {
		StringBuilder builder = new StringBuilder();
		if (StringUtil.emptyAndNull(rpur.getBuyerId())) {
			builder.append("��������������");
		}
		if (StringUtil.emptyAndNull(record.getBillId())) {
			builder.append("��������������");
		}
		return builder.toString();
	}

	private String checkBuyDate(CbRec record, CbRpur buy) {
		String buyDate = buy.getRpurDate();
		String ExpDate = record.getExpDate();
		if (DateUtil.compare(buyDate, ExpDate) >= 0) {
			return "����������������������������";
		}
		return "";
	}

	private String checkBuyer(CbRpur buy) {
		String sellerId = buy.getBuyerId();
		CusRec cus = (CusRec) this.basCusService.selectByKey(sellerId);
		if (cus == null) {
			return "������������������������";
		}
		String cusState = cus.getCusState();
		if (!"E".equals(cusState)) {
			return "��������[" + cus.getCusName() + "]��������������������������������������������������";
		}
		String acctNo = getAcctNo(sellerId);
		if (StringUtil.emptyAndNull(acctNo)) {
			return "��������[" + cus.getCusName() + "]����������������������������������������������������������";
		}
		return "";
	}
}
